(function (L5) {
"use strict";

// DDS文件参考
// http://msdn.microsoft.com/en-us/library/bb943991.aspx/

// 文件头标记
let DDS_MAGIC = 0x20534444;

let DDSD_CAPS = 0x1,
    DDSD_HEIGHT = 0x2,
    DDSD_WIDTH = 0x4,
    DDSD_PITCH = 0x8,
    DDSD_PIXELFORMAT = 0x1000,
    DDSD_MIPMAPCOUNT = 0x20000,
    DDSD_LINEARSIZE = 0x80000,
    DDSD_DEPTH = 0x800000;

let DDSCAPS_COMPLEX = 0x8,
    DDSCAPS_MIPMAP = 0x400000,
    DDSCAPS_TEXTURE = 0x1000;

let DDSCAPS2_CUBEMAP = 0x200,
    DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
    DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
    DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
    DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
    DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
    DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
    DDSCAPS2_VOLUME = 0x200000;

let DDPF_ALPHAPIXELS = 0x1,
    DDPF_ALPHA = 0x2,
    DDPF_FOURCC = 0x4,
    DDPF_RGB = 0x40,
    DDPF_YUV = 0x200,
    DDPF_LUMINANCE = 0x20000;

let FOURCC_DXT1 = 827611204;
var FOURCC_DXT1NotA = 2001;
var FOURCC_DXT3 = 2003;
var FOURCC_DXT5 = 894720068;

// 头长度为32位整数
var headerLengthInt = 31;

// 头数组偏移量
var off_magic = 0;

var off_size = 1;
var off_flags = 2;
var off_height = 3;
var off_width = 4;

var off_mipmapCount = 7;

var off_pfFlags = 20;
var off_pfFourCC = 21;


// 纹理类型定义
const UNKNOW = 0x0;
const IMAGE = 0x1;
const DDS = 0x2;
const VIDEO_ELEMENT = 0x3;

L5.Texture = function(gl, data, obj) {
    this.ambient = new Float32Array(data.ambient || [0,0,0]);
    this.diffuse = new Float32Array(data.diffuse || [0,0,0]);
    this.specular = new Float32Array(data.specular || [0,0,0]);
	// 自发光,默认不发光
    this.emissive = new Float32Array(data.emissive || [0,0,0]);
    this.shininess = data.shininess || 0;
    //this.map = data['diffuseMap'];
    this.texture = undefined;
    
    this.enableHightLight = data.hightLight || false;

    this.mapReady = false;
    this.hasTexture = false;
    this.parent = obj;

    this.loadMap(gl, data.diffuseMap);
};


L5.Texture.extChecked = -1;


/**
 * 检查是否支持扩展
 */
L5.Texture.isSupportExt = function(gl) {
    if ( L5.Texture.extChecked === -1 ) {
        var s3t =   gl.getExtension('WEBGL_compressed_texture_s3tc');
        L5.Texture.s3t = s3t;
        L5.Texture.extChecked = !!s3t;
    }

    return L5.Texture.extChecked;
};

L5.Texture.prototype = {
    constructor: L5.Texture,

    // 动态媒体更新
    update: function(gl) {},

    /**
     * 检查贴图文件类型
     */
    checkType: function(file) {
        if (typeof file === 'string') {
            let ext = file.split('.').slice(-1)[0];
            if(['jpg', 'jpeg', 'png', 'gif', 'bmp'].some(function(t){ return t=== ext; })){
                return IMAGE;
            }else if( 'dds' === ext ) {
                return DDS;
            }else{
                return UNKNOW;
            }
        }
        else if (file instanceof HTMLVideoElement) { // video element
            return VIDEO_ELEMENT;
        }
        else{
            return UNKNOW;
        }
    },


    loadMap: function(gl, path) {
        if( !path ){
            this.mapReady = true;
            return;
        }
		switch(this.checkType(path)) {
			case IMAGE:
				this.loadImage(gl, path);
				break;
			case DDS:
				// 检测是否支持扩展
				if( L5.Texture.isSupportExt(gl) ) {
					this.loadDds(gl, path);
				}else{
					this.mapReady = true;
				}
				break;
			case VIDEO_ELEMENT:
				this.loadVideo(gl, path);
				break;
			// case UNKNOW:
			default:
				this.mapReady = true;
		}
    },

    loadImage: function(gl, path){
        let self = this,
            image = new Image();

        self.texture = gl.createTexture();

        image.onload = function(){

            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

            gl.bindTexture(gl.TEXTURE_2D, self.texture);

            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);

            gl.generateMipmap(gl.TEXTURE_2D);
            gl.bindTexture(gl.TEXTURE_2D, null);
            self.setMapReady();     
        };

        image.src = path;
    },

    loadVideo: function(gl, path) {
        let that = this;
        that.texture = gl.createTexture();


        var updater = function(gl) {
            gl.bindTexture(gl.TEXTURE_2D, that.texture);
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
            //gl.pixelStorei(gl.UNPACK_FLIP_X_WEBGL, true);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, path);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
            gl.bindTexture(gl.TEXTURE_2D, null);
        };

        path.oncanplaythrough =  function() {
            that.update = updater;
            that.update(gl);
            that.setMapReady();
        };
    },


    setMapReady: function() {
        this.mapReady = true;
        this.hasTexture = true;
        this.parent.mapLoaded.call(this.parent);
    },

    loadDds: function(gl, path) {
        let self = this;
        self.texture = gl.createTexture();
		L5.XhrTask(path,'arraybuffer').then(function(content){
			gl.bindTexture(gl.TEXTURE_2D, self.texture);

			let mipmaps = self._parseDds(gl, content);
			// 控制滤波
			gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
			gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, mipmaps > 1 ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);
			gl.bindTexture(gl.TEXTURE_2D, null);
			self.setMapReady();
		});
    },

    _parseDds: function(gl, content) {
         // 获取文件头
        var header = new Int32Array(content, 0, headerLengthInt),

            ext = L5.Material.s3t,

            fourCC, blockBytes, internalFormat,
            width, height, dataLength, dataOffset,
            byteArray, mipmapCount, i;

        // 文件头错误
        if (header[off_magic] != DDS_MAGIC) {
            throw new Error("Invalid magic number in DDS header.");
        }

        // 格式不支持
        if (!header[off_pfFlags] & DDPF_FOURCC) {
            throw new Error("Unsupported format, must contain a FourCC code.");
        }

        fourCC = header[off_pfFourCC];

        // 设置格式类型
        switch (fourCC) {
            case FOURCC_DXT1NotA:
                blockBytes = 8;
                internalFormat = ext.COMPRESSED_RGB_S3TC_DXT1_EXT;
                break;
            case FOURCC_DXT1:
                blockBytes = 8;
                internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
                break;
            case FOURCC_DXT3:
                blockBytes = 16;
                internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT3_EXT;
                break;
            case FOURCC_DXT5:
                blockBytes = 16;
                internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
                break;

            default:
                throw new Error('不支持的FourCC码');
        }

        // 至少也有一张Mipmap
        mipmapCount = 1;

        // 获取Mipmap数量
        if (header[off_flags] & DDSD_MIPMAPCOUNT) {
            mipmapCount = Math.max(1, header[off_mipmapCount]);
        }

        width = header[off_width];
        height = header[off_height];
        dataOffset = header[off_size] + 4;

        // 对所有Mipmap进行压缩处理
        for (i = 0; i < mipmapCount; ++i) {
            dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes;
            byteArray = new Uint8Array(content, dataOffset, dataLength);
            // 压缩材质
            gl.compressedTexImage2D(gl.TEXTURE_2D, i, internalFormat, width, height, 0, byteArray);
            dataOffset += dataLength;
            width *= 0.5;
            height *= 0.5;
        }

        return mipmapCount;       
    }

};

})(window.L5);